﻿//One dimensional numeric array
namespace Diplom.NumericArrays
{
    using System;

    public class Numeric1DArray
    {
        #region Fields

        /// <summary>
        /// Numeric array
        /// </summary>
        Double[] raw;

        /// <summary>
        /// min, max
        /// </summary>
        double min, max;

        /// <summary>
        /// Medium Value
        /// </summary>
        double average;

        /// <summary>
        /// dispersion
        /// </summary>
        double dispersion;

        /// <summary>
        /// min time
        /// </summary>
        double timeMin;

        /// <summary>
        /// max time
        /// </summary>
        double timeMax;

        #endregion

        #region Methods

        /// <summary>
        /// Constructor
        /// </summary>
        public Numeric1DArray()
        {
            raw = new Double[100];
            min = Double.MaxValue;
            max = Double.MinValue;
            timeMax = 1.0;
            timeMin = 0.0;
            average = 0.0;
            dispersion = 0.0;
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="size">size of array</param>
        public Numeric1DArray(int size)
        {
            raw = new Double[size];
            min = Double.MaxValue;
            max = Double.MinValue;
            timeMax = size;
            timeMin = 1.0;
            average = 0.0;
            dispersion = 0.0;
        }

        /// <summary>
        /// Copy-constructor
        /// </summary>
        /// <param name="copy"></param>
        public Numeric1DArray(Numeric1DArray copy)
        {
            if (copy == null) return;
            raw = new Double[copy.Length];
            min = Double.MaxValue;
            max = Double.MinValue;
            timeMax = copy.Length;
            timeMin = 1;
            average = 0.0;
            dispersion = 0.0;
            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] = copy.Items[i];
            }
            this.InitCharacters();
        }

        /// <summary>
        /// Find extremum
        /// </summary>
        public void InitCharacters()
        {
            average = 0.0;
            dispersion = 0.0;
            for (int i = 0; i < raw.Length; i++)
            {                
                average += raw[i];
            }            
            average /= raw.Length;

            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] -= average;
                min = Math.Min(min, raw[i]);
                max = Math.Max(max, raw[i]);
                dispersion += raw[i] * raw[i];
            }
            dispersion /= (raw.Length - 1);
        }

        /// <summary>
        /// Вставка элемента по заданному индексу
        /// </summary>
        /// <param name="i"></param>
        /// <param name="item"></param>
        public void Insert(int i, double item)
        {
            raw[i] = item;
        }

        /// <summary>
        /// Объединение текущего массива с новым
        /// </summary>
        /// <param name="arrayAdd"></param>
        /// <returns></returns>
        public Numeric1DArray Concat(ref Numeric1DArray arrayAdd)
        {
            Numeric1DArray newNumeric1DArray = new Numeric1DArray(this.Length + arrayAdd.Length);
            for (int i = 0; i < this.Length; i++)
            {
                newNumeric1DArray.Items[i] = this.Items[i];
            }
            for (int i = 0; i < arrayAdd.Length; i++)
            {
                newNumeric1DArray.Items[i + this.Length] = arrayAdd.Items[i];
            }
            newNumeric1DArray.timeMin = 1;
            newNumeric1DArray.timeMax = newNumeric1DArray.Length;
            newNumeric1DArray.InitCharacters();
            return newNumeric1DArray;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Minimum
        /// </summary>
        public double Min
        {            
            get
            {                
                return min;
            }
            set
            {
                min = value;//!!!
            }
        }

        /// <summary>
        /// Maximum
        /// </summary>
        public double Max
        {
            get
            {
                return max;
            }
            set
            {
                max = value;//!!!
            }
        }

        /// <summary>
        /// Среднее
        /// </summary>
        public double Average
        {
            get
            {
                return average;
            }
            set
            {
                average = value;
            }
        }

        /// <summary>
        /// Дисперсия
        /// </summary>
        public double Dispersion
        {
            get
            {
                return dispersion;
            }
            set
            {
                dispersion = value;
            }
        }

        /// <summary>
        /// Size
        /// </summary>
        public int Length
        {
            get
            {
                if (raw == null) { return -1; }
                return raw.Length;
            }
        }

        /// <summary>
        /// Data
        /// </summary>
        public Double[] Items
        {
            get
            {
                return raw;
            }
            set
            {
                raw = value;
            }

        }

        /// <summary>
        /// Begin time interval
        /// </summary>
        public double TimeMin
        {
            get
            {
                return timeMin;
            }
            set
            {
                timeMin = value;
            }
        }

        /// <summary>
        /// End time interval
        /// </summary>
        public double TimeMax
        {
            get
            {
                return timeMax;
            }
            set
            {
                timeMax = value;
            }
        }

        #endregion
    }
}
